home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / amiga / bmake15.lzh / fncall.c < prev    next >
C/C++ Source or Header  |  1991-10-23  |  16KB  |  743 lines

  1. /*    fncall.c
  2.  *    (c) Copyright 1991 by Ben Eng, All Rights Reserved
  3.  *
  4.  */
  5.  
  6. #include <clib/exec_protos.h>
  7.  
  8. #include <ctype.h>
  9. #include <scdir.h>
  10.  
  11. #include "make.h"
  12. #include "depend.h"
  13.  
  14. #if FNCALLS
  15.  
  16. /*    function calls (mac, string)
  17.  *
  18.  *    The string parameter is the rest of the arguments passed to the
  19.  *    function call.  string is modifiable in fncalls because it is
  20.  *    actually contained within the macroname array[] which isn't
  21.  *    really used again after the fncall returns.
  22.  *
  23.  *    returns 0 if successful, 1 if error
  24.  *    with side effect:  mac->expansion = strdup( result_string );
  25.  *
  26.  */
  27.  
  28. static char argument_missing[] = "argument missing: %s %s\n";
  29. static char error_no_memory[] = "error:  no memory\n";
  30.  
  31. static int
  32. do_basename( struct macro *mac, char *string, how_basename )
  33. {
  34.     char *filelist = NULL;
  35.     char *out, *text, *cptr;
  36.     int len = 0;
  37.     char word[ MAXPATHNAME ];
  38.  
  39.     filelist = (char *)calloc( Param.MaxLine, 1 );
  40.     if( !filelist ) {
  41.         logfile( error_no_memory );
  42.         return( 1 );
  43.     }
  44.     
  45.     out = filelist;
  46.     text = string;
  47.  
  48.     while( len < Param.MaxLine ) {
  49.         text = parse_str( word, text, sizeof(word));
  50.         if( !*word )
  51.             break; /* no more words in text */
  52.         cptr = strrchr( word, '.' );
  53.         if( how_basename ) { /* take the basename */
  54.             if( cptr && basename(word) <= cptr ) {
  55.                 *cptr = (char)0; /* truncate the word at the `.' */
  56.             }
  57.         }
  58.         else { /* take the suffix */
  59.             if( cptr && basename(word) <= cptr ) {
  60.                 shift_string_left( word, (int)(cptr - word));
  61.             }
  62.         }
  63.         len += strlen( word );
  64.         if( len + 1 < Param.MaxLine ) {
  65.             if( out != filelist ) {
  66.                 *out++ = ' ';
  67.                 len++;
  68.             }
  69.             strcpy( out, word );
  70.             out = filelist + len;
  71.         }
  72.         else break;
  73.     } /* while */
  74.     *out = (char)0;
  75.     if( len > 0 )
  76.         mac->expansion = strdup( filelist );
  77.     free( filelist );
  78.     return( 0 );
  79. }
  80.  
  81. static int
  82. fn_basename( struct macro *mac, char *string )
  83. {
  84.     return( do_basename( mac, string, 1 ));
  85. }
  86.  
  87. static int
  88. fn_suffix( struct macro *mac, char *string )
  89. {
  90.     return( do_basename( mac, string, 0 ));
  91. }
  92.  
  93. static int
  94. do_addfix( struct macro *mac, char *string, int how_fix )
  95. {
  96.     char *filelist = NULL;
  97.     char *suf, *str = string;
  98.  
  99.     filelist = (char *)calloc( Param.MaxLine, 1 );
  100.     if( !filelist ) {
  101.         logfile( error_no_memory );
  102.         return( 1 );
  103.     }
  104.  
  105.     while( isspace( *str )) str++;
  106.     suf = str;
  107.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  108.     if( *suf != ',' && *str == ',' && str[-1] != '\\' ) {
  109.         char *out, *text, *cptr;
  110.         int suflen, len = 0;
  111.         char word[ MAXPATHNAME ];
  112.  
  113.         *str++ = (char)0; /* null terminate the suffix */
  114.         suflen = strlen( suf );
  115.         out = filelist;
  116.         text = str;
  117.  
  118.         while( len < Param.MaxLine ) {
  119.             text = parse_str( word, text, sizeof(word));
  120.             if( !*word )
  121.                 break; /* no more words in text */
  122.             if( (strlen( word )+suflen) < sizeof(word)) {
  123.                 if( how_fix ) /* append the suffix */
  124.                     strcat( word, suf );
  125.                 else { /* prepend the prefix */
  126.                     len += strlen( suf );
  127.                     if( len + 1 < Param.MaxLine ) {
  128.                         if( out != filelist ) {
  129.                             *out++ = ' ';
  130.                             len++;
  131.                         }
  132.                         strcpy( out, suf );
  133.                         out = filelist + len;
  134.                     }
  135.                 }
  136.             }
  137.             len += strlen( word );
  138.             if( len + 1 < Param.MaxLine ) {
  139.                 if( out != filelist & how_fix ) {
  140.                     *out++ = ' ';
  141.                     len++;
  142.                 }
  143.                 strcpy( out, word );
  144.                 out = filelist + len;
  145.             }
  146.             else break;
  147.         } /* while */
  148.         *out = (char)0;
  149.         if( len > 0 )
  150.             mac->expansion = strdup( filelist );
  151.     }
  152.     free( filelist );
  153.     return( 0 );
  154. }
  155.  
  156. static int
  157. fn_addprefix( struct macro *mac, char *string )
  158. {
  159.     return( do_addfix( mac, string, 0 ));
  160. }
  161.  
  162. static int
  163. fn_addsuffix( struct macro *mac, char *string )
  164. {
  165.     return( do_addfix( mac, string, 1 ));
  166. }
  167.  
  168. static int
  169. do_dir( struct macro *mac, char *string, int how_dir )
  170. {
  171.     char *filelist = NULL;
  172.     char *str = string;
  173.     char *out, *text, *cptr;
  174.     int len = 0;
  175.     char word[ MAXPATHNAME ];
  176.  
  177.     filelist = (char *)calloc( Param.MaxLine, 1 );
  178.     if( !filelist ) {
  179.         logfile( error_no_memory );
  180.         return( 1 );
  181.     }
  182.  
  183.     while( isspace( *str )) str++;
  184.     out = filelist;
  185.     text = str;
  186.  
  187.     while( len < Param.MaxLine ) {
  188.         text = parse_str( word, text, sizeof(word));
  189.         if( !*word )
  190.             break; /* no more words in text */
  191.         cptr = basename( word );
  192.         if( how_dir ) { /* keep only the directory part */
  193.             *cptr = (char)0;
  194.         }
  195.         else { /* prepend the prefix */
  196.             shift_string_left( word, (int)(cptr - word));
  197.         }
  198.         len += strlen( word );
  199.         if( len + 1 < Param.MaxLine ) {
  200.             if( out != filelist ) {
  201.                 *out++ = ' ';
  202.                 len++;
  203.             }
  204.             strcpy( out, word );
  205.             out = filelist + len;
  206.         }
  207.         else break;
  208.     } /* while */
  209.     *out = (char)0;
  210.     if( len > 0 )
  211.         mac->expansion = strdup( filelist );
  212.     free( filelist );
  213.     return( 0 );
  214. }
  215.  
  216. static int
  217. fn_dir( struct macro *mac, char *string )
  218. {
  219.     return( do_dir( mac, string, 1 ));
  220. }
  221.  
  222. static int
  223. fn_notdir( struct macro *mac, char *string )
  224. {
  225.     return( do_dir( mac, string, 0 ));
  226. }
  227.  
  228. static int
  229. do_filter( struct macro *mac, char *string, int how_filter )
  230. {
  231.     char *str = string;
  232.     char *pat;
  233.     int len;
  234.  
  235.     while( isspace( *str )) str++;
  236.     pat = str;
  237.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  238.     if( *pat != ',' && *str == ',' && str[-1] != '\\' ) {
  239.         char word[ 80 ];
  240.         char *text, *out;
  241.  
  242.         *str++ = (char)0;
  243.  
  244.         if( !( mac->expansion = strdup( str )))
  245.             return( 0 ); /* no mem */
  246.         out = mac->expansion;
  247.  
  248.         for( text = out;; ) {
  249.             text = parse_str( word, text, sizeof(word));
  250.             if( !*word )
  251.                 break; /* no more words in text */
  252.  
  253.             if( how_filter ) {
  254.                 if( pattern_match( pat, word )) {
  255.                     out = text + 1;
  256.                 }
  257.                 else { /* no match remove it */
  258.                     while( isspace( *text )) text++;
  259.                     shift_string_left( out, (int)(text - out));
  260.                     text = out;
  261.                 }
  262.             }
  263.             else {
  264.                 if( pattern_match( pat, word )) {
  265.                     while( isspace( *text )) text++;
  266.                     shift_string_left( out, (int)(text - out));
  267.                     text = out;
  268.                 }
  269.                 else { /* no match remove it */
  270.                     out = text + 1;
  271.                 }
  272.             }
  273.         } /* for */
  274.         *out = (char)0;
  275.         return( 0 );
  276.     }
  277.     logprintf( argument_missing, "filter", string );
  278.     return( 1 );
  279. }
  280.  
  281. static int
  282. fn_filter( struct macro *mac, char *string )
  283. {
  284.     return( do_filter( mac, string, 1 ));
  285. }
  286.  
  287. static int
  288. fn_filter_out( struct macro *mac, char *string )
  289. {
  290.     return( do_filter( mac, string, 0 ));
  291. }
  292.  
  293. static int
  294. fn_findstring( struct macro *mac, char *string )
  295. {
  296.     char *find, *in, *str = string;
  297.     int len;
  298.     
  299.     while( isspace( *str )) str++;
  300.     find = str;
  301.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  302.     if( *find != ',' && *str == ',' && str[-1] != '\\' ) {
  303.         *str++ = (char)0;
  304.         in = str;
  305.         while( *str ) str++;    /* find end string */
  306.         len = strlen( find );
  307.         str -= len;    /* str marks the end of searching */
  308.  
  309.         while( in <= str ) {
  310.             if( !strnicmp( find, in, len )) { /* found */
  311.                 mac->expansion = strdup( find );
  312.                 break;
  313.             }
  314.             in++; 
  315.         }
  316.     }
  317.     else {
  318.         logprintf( argument_missing, "findstring", string );
  319.         return( 1 );
  320.     }
  321.     return( 0 );
  322. }
  323.  
  324. static int
  325. fn_getenv( struct macro *mac, char *string )
  326. {
  327.     char *evalue;
  328.     while( isspace( *string )) string++;
  329.  
  330.     evalue = getenv( string );
  331.     if( evalue && *evalue )
  332.         mac->expansion = strdup( evalue );
  333.     return( 0 );
  334. }
  335.  
  336. static int
  337. fn_join( struct macro *mac, char *string )
  338. {
  339.     char *filelist = NULL;
  340.     char *str = string;
  341.     char *text1, *text2;
  342.     
  343.     filelist = (char *)calloc( Param.MaxLine, 1 );
  344.     if( !filelist ) {
  345.         logfile( error_no_memory );
  346.         return( 1 );
  347.     }
  348.  
  349.     while( isspace( *str )) str++;
  350.     text1 = str;
  351.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  352.     if( *text1 != ',' && *str == ',' && str[-1] != '\\' ) {
  353.         char *out;
  354.         int len = 0;
  355.         char word1[ MAXPATHNAME ], word2[ MAXPATHNAME ];
  356.  
  357.         *str++ = (char)0; /* null terminate the suffix */
  358.         out = filelist;
  359.         text2 = str;
  360.  
  361.         *word1 = *word2 = ' '; /* dummy for first iteration */
  362.         while( len < Param.MaxLine ) {
  363.             if( *word1 )
  364.                 text1 = parse_str( word1, text1, sizeof(word1));
  365.             if( *word2 )
  366.                 text2 = parse_str( word2, text2, sizeof(word2));
  367.             if( !*word1 && !*word2 )
  368.                 break; /* no more words */
  369.  
  370.             len += strlen( word1 ) + strlen( word2 );
  371.             if( len + 1 < Param.MaxLine ) {
  372.                 if( out != filelist ) {
  373.                     *out++ = ' ';
  374.                     len++;
  375.                 }
  376.                 strcpy( out, word1 );
  377.                 strcat( out, word2 );
  378.                 out = filelist + len;
  379.             }
  380.             else break;
  381.         } /* while */
  382.         *out = (char)0;
  383.         if( len > 0 )
  384.             mac->expansion = strdup( filelist );
  385.     }
  386.     if( filelist )
  387.         free( filelist );
  388.     return( 0 );
  389. }
  390.  
  391. static int
  392. fn_patsubst( struct macro *mac, char *string )
  393. {
  394.     char *str = string;
  395.     char *from, *to, *text;
  396.     
  397.     while( isspace( *str )) str++;
  398.     from = str;
  399.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  400.     if( *from != ',' && *str == ',' && str[-1] != '\\' ) {
  401.         *str++ = (char)0;
  402.         to = str;
  403.         while( *str && *str != ',' && str[-1] != '\\' ) str++;
  404.         if( *to != ',' && *str == ',' && str[-1] != '\\' && str[ 1 ] ) {
  405.             char *expansion = NULL, *out;
  406.             int len = 0;
  407.  
  408.             *str++ = (char)0;
  409.             while( *str && isspace( *str )) str++;
  410.             text = str;
  411.  
  412.             out = expansion = (char *)malloc( Param.MaxLine );
  413.             if( !expansion ) {
  414.                 logfile( error_no_memory );
  415.                 return( 1 );
  416.             }
  417.             while( *str ) {
  418.                 while( *str && !isspace( *str )) str++;
  419.                 if( !*str && str == text )
  420.                     break;
  421.                 if( *str )
  422.                     *str++ = (char)0;
  423.                 if( len + (int)(str - text) < Param.MaxLine ) {
  424.                     if( out > expansion ) {
  425.                         *out++ = ' ';
  426.                         len++;
  427.                     }
  428.                     if( pattern_match( from, text )) {
  429.                         /* needs to do bounds checking to prevent */
  430.                         /* overflowing of the expansion string! */
  431.                         /* neglected for now - user discretion advised */
  432.                         if( map_to_pattern( out, from, to, text ))
  433.                             break;
  434.                     }
  435.                     else strcpy( out, text );
  436.                 }
  437.                 len += strlen( out );
  438.                 out = expansion + len;
  439.                 while( *str && isspace( *str )) str++;
  440.                 text = str;
  441.             }
  442.             *out = (char)0;
  443.             if( *expansion )
  444.                 mac->expansion = strdup( expansion );
  445.             free( expansion );
  446.             return( 0 );
  447.         }
  448.     }
  449.     logprintf( argument_missing, "patsubst", string );
  450.     return( 1 );
  451. }
  452.  
  453. static int
  454. sortcomp( char **s1, char **s2 )
  455. {
  456.     return( stricmp( *s1, *s2 ));
  457. }
  458.  
  459. static int
  460. fn_sort( struct macro *mac, char *string )
  461. {
  462.     int i, nel;
  463.     char **array = NULL;
  464.     char *expansion = NULL;
  465.     char *out, *str = string;
  466.  
  467.     while( isspace( *str )) str++;
  468.     nel = count_args( str );
  469.     array = (char **)calloc( sizeof(char *), nel );
  470.     expansion = (char *)malloc( Param.MaxLine );
  471.     if( !array || !expansion ) {
  472.         logfile( error_no_memory );
  473.         if( array )
  474.             free( array );
  475.         if( expansion )
  476.             free( expansion );
  477.         return( 1 );
  478.     }
  479.  
  480.     for( i = 0; i < nel && *str; i++ ) {
  481.         while( isspace( *str ))
  482.             str++;
  483.         if( *str )
  484.             array[ i ] = str++;
  485.         while( !isspace( *str ) && *str )
  486.             str++;
  487.         if( isspace( *str ))
  488.             *str++ = (char)0;
  489.     }
  490.  
  491.     qsort( array, nel, sizeof(char *), sortcomp );
  492.     out = expansion;
  493.     for( i = 0; i < nel; i++ ) {
  494.         if( i )
  495.             *out++ = ' ';
  496.         strcpy( out, array[ i ] );
  497.         out += strlen( out );
  498.     }
  499.  
  500.     free( array );
  501.     mac->expansion = strdup( expansion );
  502.     free( expansion );
  503.     return( 0 );
  504. }
  505.  
  506. static int
  507. fn_strip( struct macro *mac, char *str )
  508. {
  509.     while( isspace( *str )) str++;
  510.     if( *str && (mac->expansion = strdup( str ))) {
  511.         register char *d = mac->expansion;
  512.         register char *s = mac->expansion;
  513.         while( *s ) {
  514.             *d++ = *s;
  515.             if( isspace(*s))
  516.                 while( isspace( *s)) s++;
  517.             else
  518.                 s++;
  519.         }
  520.         if( isspace( *d )) {
  521.             while( isspace( *d ) && d > mac->expansion )
  522.                 d--;
  523.             d++;
  524.         }
  525.         *d = (char)0;
  526.     }
  527.     return( 0 );
  528. }
  529.  
  530. static int
  531. fn_subst( struct macro *mac, char *string )
  532. {
  533.     char *str = string;
  534.     char *from, *to, *text, *out;
  535.     char *expansion = NULL;
  536.     int fromlen, tolen;
  537.     
  538.     while( isspace( *str )) str++;
  539.     from = str;
  540.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  541.     if( *from != ',' && *str == ',' && str[-1] != '\\' ) {
  542.         *str++ = (char)0;
  543.         to = str;
  544.         while( *str && *str != ',' && str[-1] != '\\' )
  545.             str++;
  546.         if( *to != ',' && *str == ',' && str[-1] != '\\' && str[ 1 ] ) {
  547.             *str++ = (char)0;
  548.             text = str;
  549.             fromlen = strlen( from );
  550.             tolen = strlen( to );
  551.             while( *str ) str++;    /* find end string */
  552.             str -= fromlen;
  553.  
  554.             out = expansion = (char *)malloc( Param.MaxLine );
  555.             if( !expansion ) {
  556.                 logfile( error_no_memory );
  557.                 return( 1 );
  558.             }
  559.             while( text <= str ) {
  560.                 if( !strnicmp( from, text, fromlen )) { /* found */
  561.                     if( (int)(out - expansion) + tolen < Param.MaxLine ) {
  562.                         strcpy( out, to );
  563.                         out += tolen;
  564.                     }
  565.                     else break;
  566.                     text += fromlen;
  567.                 }
  568.                 else if((int)(out - expansion) + tolen < Param.MaxLine ) {
  569.                     *out++ = *text++;
  570.                 }
  571.                 else break;
  572.             }
  573.             *out = (char)0;
  574.             if( *expansion )
  575.                 mac->expansion = strdup( expansion );
  576.             free( expansion );
  577.             return( 0 );
  578.         }
  579.     }
  580.     logprintf( argument_missing, "subst", string );
  581.     return( 1 );
  582. }
  583.  
  584. static int
  585. fn_wildcard( struct macro *mac, char *string )
  586. {
  587.     char *filelist = NULL;
  588.     char *pat = string;
  589.  
  590.     filelist = (char *)calloc( Param.MaxLine, 1 );
  591.     if( !filelist ) {
  592.         logfile( error_no_memory );
  593.         return( 1 );
  594.     }
  595.     while( isspace( *pat )) pat++;
  596.     if( *pat ) {
  597.         char *out = filelist;
  598.         char *fn;
  599.         int len = 0;
  600.  
  601.         while( len < Param.MaxLine ) {
  602.             if( !(fn = scdir( pat )))
  603.                 break; /* no more */
  604.             if( out != filelist ) {
  605.                 *out++ = ' ';
  606.                 len++;
  607.             }
  608.             len += strlen( fn );
  609.             if( len < Param.MaxLine ) {
  610.                 strcpy( out, fn );
  611.                 out = filelist + len;
  612.             }
  613.         }
  614.         if( len > 0 )
  615.             mac->expansion = strdup( filelist );
  616.         scdir_abort();
  617.     }
  618.     free( filelist );
  619.     return( 0 );
  620. }
  621.  
  622.  
  623. int
  624. do_word( struct macro *mac, char *string, int word )
  625. {
  626.     char *begin, *end;
  627.  
  628.     if( begin = find_word( string, word )) {
  629.         end = begin;
  630.         while( *end && !isspace( *end )) end++;
  631.         *end = (char)0; /* null terminate past the end of word */
  632.         mac->expansion = strdup( begin );
  633.     }
  634.     return( 0 );
  635. }
  636.  
  637. static int
  638. fn_firstword( struct macro *mac, char *string )
  639. {
  640.     while( isspace( *string )) string++;
  641.     return( do_word( mac, string, 1 ));
  642. }
  643.  
  644. static int
  645. fn_word( struct macro *mac, char *string )
  646. {
  647.     char *comma;
  648.     int word;
  649.  
  650.     while( isspace( *string )) string++;
  651.     if( *string && (comma = find_token( string, ',' ))) {
  652.         *comma = (char)0;
  653.         word = atoi( string );
  654.         /* else word not found */
  655.         return( do_word( mac, comma + 1, word ));
  656.     }
  657.     logprintf( argument_missing, "word", string );
  658.     return( 1 );
  659. }
  660.  
  661. static int
  662. fn_words( struct macro *mac, char *string )
  663. {
  664.     char buf[ 20 ];
  665.     sprintf( buf, "%d", count_args( string ));
  666.     mac->expansion = strdup( buf );
  667.     return( 0 );
  668. }
  669.  
  670. static int
  671. fn_notimp( struct macro *mac, char *string )
  672. {
  673.     logfile( "Function call not implemented\n" );
  674.     return( 1 );
  675. }
  676.  
  677. /*************************************************************************/
  678.  
  679. /* sorted array for binary search */
  680. #define MAX_FNCALL 22
  681. static struct fncall fncarray[ MAX_FNCALL ] = {
  682.     "addprefix",    fn_addprefix,
  683.     "addsuffix",    fn_addsuffix,
  684.     "basename",        fn_basename,
  685.     "dir",            fn_dir,
  686.     "filter",        fn_filter,
  687.     "filter-out",    fn_filter_out,
  688.     "findstring",    fn_findstring,
  689.     "firstword",    fn_firstword,
  690.     "foreach",        fn_notimp,
  691.     "getenv",        fn_getenv,
  692.     "join",            fn_join,
  693.     "notdir",        fn_notdir,
  694.     "origin",        fn_notimp,
  695.     "patsubst",        fn_patsubst,
  696.     "shell",        fn_notimp,
  697.     "sort",            fn_sort,
  698.     "strip",        fn_strip,
  699.     "subst",        fn_subst,
  700.     "suffix",        fn_suffix,
  701.     "wildcard",        fn_wildcard,
  702.     "word",            fn_word,
  703.     "words",        fn_words
  704. };
  705.  
  706. /*    binary search to find the function */
  707. struct fncall *
  708. find_fncall( char *name )
  709. {
  710.     register struct fncall *array = fncarray;
  711.     int first = 0;
  712.     int last = MAX_FNCALL - 1;
  713.     int mid;
  714.     int diff;
  715.  
  716.     /* binary search */
  717.     while( first <= last ) {
  718.         mid = (first+last) / 2;
  719.         diff = stricmp( name, array[ mid ].name );
  720.         if( !diff )
  721.             return( &array[ mid ] ); /* found */
  722.         if( first == last )
  723.             break; /* not found */
  724.         if( diff < 0 )
  725.             last = mid - 1;
  726.         else
  727.             first = mid + 1;
  728.     }
  729.     return( NULL ); /* not found */
  730. }
  731.  
  732. #else
  733.  
  734. /*    No FNCALLS */
  735. struct fncall *
  736. find_fncall( char *name )
  737. {
  738.     return( NULL ); /* not found */
  739. }
  740.  
  741. #endif
  742.  
  743.